#include <iostream>
#include <cctype>
#include <algorithm>
#include "Node.h"

using namespace std;
namespace htmlcxx
{
	namespace HTML
	{
		void Node::parseAttributes()
		{
			if (!(this->isTag())) return;

			const wchar_t *end;
			const wchar_t *ptr = mText.c_str();
			if ((ptr = wcschr(ptr, L'<')) == 0) return;
			ptr++;

			// Skip initial blankspace
			while (iswspace(*ptr)) 
				ptr++;

			// Skip tagname
			if (!iswalpha(*ptr)) return;

			// here is a bug!
			while (!iswspace(*ptr) && *ptr!=L'>') // need to consider the tag has no arttibutes and no space in it. for example: <span>hello</span>
				ptr++;

			// Skip blankspace after tagname
			while (iswspace(*ptr)) 
				ptr++;

			while (*ptr && *ptr != L'>')
			{
				wstring key, val;

				// skip unrecognized
				while (*ptr && !iswalnum(*ptr) && !iswspace(*ptr)) 
					ptr++;

				// skip blankspace
				while (iswspace(*ptr)) 
					ptr++;

				end = ptr;
				while (iswalnum(*end) || *end == L'-') 
					end++;
				key.assign(end - ptr, L'\0');
				transform(ptr, end, key.begin(), ::towlower);
				ptr = end;

				// skip blankspace
				while (iswspace(*ptr)) 
					ptr++;

				if (*ptr == L'=')
				{
					ptr++;
					while (iswspace(*ptr)) 
						ptr++;
					if (*ptr == L'"' || *ptr == L'\'')
					{
						wchar_t quote = *ptr;
						//				fprintf(stderr, "Trying to find quote: %c\n", quote);
						const wchar_t *end = wcschr(ptr + 1, quote);
						if (end == 0)
						{
							//b = mText.find_first_of(" >", a+1);
							const wchar_t *end1, *end2;
							end1 = wcschr(ptr + 1, L' ');
							end2 = wcschr(ptr + 1, L'>');
							if (end1 && end1 < end2) end = end1;
							else end = end2;
							if (end == 0) return;
						}
						const wchar_t *begin = ptr + 1;
						while (iswspace(*begin) && begin < end) 
							begin++;
						const wchar_t *trimmed_end = end - 1;
						while (iswspace(*trimmed_end) && trimmed_end >= begin)
							trimmed_end--;
						val.assign(begin, trimmed_end + 1);
						ptr = end + 1;
					}
					else
					{
						end = ptr;
						while (*end && !iswspace(*end) && *end != L'>') 
							end++;
						val.assign(ptr, end);
						ptr = end;
					}

					//			fprintf(stderr, "%s = %s\n", key.c_str(), val.c_str());
					mAttributes.insert(make_pair(key, val));
				}
				else
				{
					//			fprintf(stderr, "D: %s\n", key.c_str());
					mAttributes.insert(make_pair(key, wstring()));
				}
			}
		}

		bool Node::operator==(const Node &n) const
		{
			if (!isTag() || !n.isTag()) return false;
			return !(_wcsicmp(tagName().c_str(), n.tagName().c_str()));
		}

		Node::operator wstring() const {
			if (isTag()) return this->tagName();
			return this->text();
		}

		wostream &Node::operator<<(wostream &stream) const {
			stream << (wstring)(*this);
			return stream;
		}
	}
}
